package com.example.demo.filter;

import com.example.demo.DemoProperties;
import com.example.demo.commons.SessionManager;
import com.example.demo.commons.SsoClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.stream.Stream;

@Component
@WebFilter(urlPatterns = "/**")
public class SessionFilter implements Filter {

    private final Logger log = LoggerFactory.getLogger(getClass());
    private final DemoProperties demoProperties;
    private final SessionManager sessionManager;
    private final SsoClient ssoClient;

    @Autowired
    public SessionFilter(final DemoProperties demoProperties,
                         final SessionManager sessionManager,
                         final SsoClient ssoClient) {
        this.demoProperties = demoProperties;
        this.sessionManager = sessionManager;
        this.ssoClient = ssoClient;
    }


    @Override
    public void doFilter(final ServletRequest request,
                         final ServletResponse response,
                         final FilterChain chain)
            throws IOException, ServletException {
        final var httpRequest = (HttpServletRequest) request;
        final var httpResponse = (HttpServletResponse) response;

        final var servletPath = httpRequest.getServletPath();
        final var ignore = Stream.of("/favicon.ico", "/error")
                .anyMatch(item -> item.equals(servletPath));
        if (ignore) {
            chain.doFilter(request, response);
            return;
        }

        final var appCode = sessionManager.getAppCode();

        // 不用的appCode表示不同的公众号，不同的公众号持有不同的会话属性
        final var sessionObject = sessionManager.getSessionObject();

        if (sessionObject.getOpenid() != null) { // 用户已登录
            chain.doFilter(request, response);
            return;
        }

        // 用户登录第2步：根据返回的授权码获取用户openid
        if (httpRequest.getRequestURI().endsWith("/login")) {
            final var code = httpRequest.getParameter("code");
            final var state = httpRequest.getParameter("state");
            log.debug("获取用户openid：code={}，state={}", code, state);
            final var openid = ssoClient.getOpenid(code); // 根据code查询用户信息
            sessionObject.setOpenid(openid); // 设置会话所关联的openid
            httpResponse.sendRedirect(demoProperties.getLocalBaseUrl() + state);
            return;
        }

        // 用户登录第1步：跳转授权连接获取授权码
        final var loginUrl = demoProperties.getLocalBaseUrl() + "/" + appCode + "/login";
        final String bizUri = httpRequest.getRequestURI() + getQueryString(httpRequest);
        final var redirectUrl = demoProperties.getSsoServiceUrl() + "/" + appCode + "/auth"
                + "?client_code=" + demoProperties.getClientId()
                + "&redirect_uri=" + URLEncoder.encode(loginUrl, StandardCharsets.UTF_8)
                + "&state=" + URLEncoder.encode(bizUri, StandardCharsets.UTF_8);
        log.debug("重定向授权地址：{}", redirectUrl);
        httpResponse.sendRedirect(redirectUrl);
    }

    private String getQueryString(final HttpServletRequest request) {
        return request.getQueryString() == null ? "" : "?" + request.getQueryString();
    }
}
